home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 424_01 / ed_157 / do_grep.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-10  |  5.0 KB  |  158 lines

  1. /*
  2.  * Copyright (C) 1992 by Rush Record (rhr@clio.rice.edu)
  3.  * 
  4.  * This file is part of ED.
  5.  * 
  6.  * ED is free software; you can redistribute it and/or modify it under the terms
  7.  * of the GNU General Public License as published by the Free Software Foundation.
  8.  * 
  9.  * ED is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  10.  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  11.  * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  12.  * 
  13.  * You should have received a copy of the GNU General Public License along with ED
  14.  * (see the file COPYING).  If not, write to the Free Software Foundation, 675
  15.  * Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17. #include "opsys.h"
  18.  
  19. #include <stdio.h>
  20. #include <string.h>
  21.  
  22. #include "memory.h"
  23. #include "rec.h"
  24. #include "buffer.h"
  25. #include "window.h"
  26. #include "ed_dec.h"
  27. #include "cmd_enum.h"
  28.  
  29. /******************************************************************************\
  30. |Routine: grep_report_skip
  31. |Callby: do_grep
  32. |Purpose: Reports how many lines did/didn't match.
  33. |Arguments:
  34. |    LINES - the number of lines to report.
  35. |    FUNCTION - either 'skip' or 'match'.
  36. |    BASE - the grep buffer base.
  37. \******************************************************************************/
  38. void grep_report_skip(lines,function,base)
  39. Int lines;
  40. Char *function;
  41. rec_ptr base;
  42. {
  43.     rec_ptr new;
  44.     Char buf[128];
  45.     Int length;
  46.     
  47.     new = (rec_ptr)imalloc(sizeof(rec_node));
  48.     sprintf(buf,"<%s %d %s>",function,lines,(lines > 1)? "lines" : "line");
  49.     new->data = (Char *)imalloc((length = strlen(buf)) + 1);
  50.     memcpy(new->data,buf,length);
  51.     new->data[length] = '\0';
  52.     new->length = length;
  53.     new->recflags = 1;    /* it is a freeable buffer */
  54.     insq(new,base->prev);
  55. }
  56.  
  57. /******************************************************************************\
  58. |Routine: grep_report_line
  59. |Callby: do_grep
  60. |Purpose: Puts a matching/non-matching line in the grep record queue.
  61. |Arguments:
  62. |    REC - the record to add to the queue.
  63. |    BASE - the grep buffer base.
  64. \******************************************************************************/
  65. void grep_report_line(rec,base)
  66. rec_ptr rec,base;
  67. {
  68.     rec_ptr new;
  69.     
  70.     new = (rec_ptr)imalloc(sizeof(rec_node));    /* report contents of line */
  71.     new->data = (Char *)imalloc(rec->length + 1);
  72.     memcpy(new->data,rec->data,new->length = rec->length);
  73.     new->data[rec->length] = '\0';
  74.     new->recflags = 1;    /* it is a freeable buffer */
  75.     insq(new,base->prev);
  76. }
  77.  
  78. /******************************************************************************\
  79. |Routine: do_grep
  80. |Callby: command
  81. |Purpose: Generates a buffer with grep'd records and spacers.
  82. |Arguments:
  83. |    OLDBASE - the buffer the user is searching for ALL occurrences of the string in.
  84. |    NEWBASE - the buffer that will be created.
  85. |    STRING - the string to search for.
  86. |    GREPPERG - =1 means GREP, =0 means PERG (opposite of GREP).
  87. |    SILENT - flag that <skip...> lines should not appear.
  88. \******************************************************************************/
  89. void do_grep(oldbase,newbase,string,grepperg,silent)
  90. rec_ptr oldbase,newbase;
  91. Int grepperg;
  92. Char *string;
  93. Int silent;
  94. {
  95.     rec_ptr prev,rec,save_prev;
  96.     buf_node search;
  97.     Int byt,lines,hits;
  98.     Char search_flags[5];
  99.     
  100. /* initialize */
  101.     rec = (save_prev = prev = oldbase)->next;
  102.     byt = 0;
  103.     hits = 0;
  104. /* make an empty buffer to hold the search string */
  105.     search.first = (rec_ptr)&search.first;
  106.     search.last = (rec_ptr)&search.first;
  107.     string_to_buf(string,&search);
  108. /* copy current search flags */
  109.     memcpy(search_flags,SEARCH_FLAGS,((int)NUM_SMODES) >> 1);
  110.     search_flags[1] = 'e';    /* set end mode for search, so we can match first record if it matches the search string at offset 0 */
  111. /* find instances of the search string */
  112.     while(find_string(rec,byt,1,&search,search_flags,1))
  113.     {
  114.         get_string_loc(&rec,&byt);    /* get new location */
  115.         save_prev = prev;
  116.         for(lines = -1;prev != rec;prev = prev->next,lines++);    /* count lines skipped */
  117.         if(lines >= 0)    /* if we're not still on the same record... */
  118.         {
  119.             if(grepperg)
  120.             {
  121.                 if(lines > 0 && !silent)    /* if we skipped more than one line forward, report skip */
  122.                     grep_report_skip(lines,"skip",newbase);
  123.                 grep_report_line(rec,newbase);
  124.             }
  125.             else
  126.             {
  127.                 if(lines > 0)
  128.                 {
  129.                     if(hits && !silent)    /* report skip over matching lines */
  130.                         grep_report_skip(hits,"match",newbase);
  131.                     while(lines--)
  132.                         grep_report_line(save_prev = save_prev->next,newbase);
  133.                     hits = 1;
  134.                 }
  135.                 else
  136.                     hits++;
  137.                 save_prev = prev;    /* we have to do this, in case this was the last match in the file. it prevents the code at the end
  138.                                        from reporting the line containing the search string. */
  139.             }
  140.         }
  141.     }
  142. /* report on the tail end of the file */
  143.     if(grepperg)
  144.     {
  145.         for(lines = -1;prev != oldbase;prev = prev->next,lines++);    /* count lines skipped */
  146.         if(lines > 0 && !silent)
  147.             grep_report_skip(lines,"skip",newbase);
  148.     }
  149.     else
  150.     {
  151.         if(hits && !silent)    /* report skip over matching lines */
  152.             grep_report_skip(hits,"match",newbase);
  153.         while((save_prev = save_prev->next) != oldbase)
  154.             grep_report_line(save_prev,newbase);
  155.     }
  156. }
  157.  
  158.